package ai.xiaodao.trade;

import ai.xiaodao.config.BrokerConfig;
import ai.xiaodao.db.OrderOps;
import com.futu.openapi.FTAPI_Conn;
import com.futu.openapi.FTAPI_Conn_Trd;
import com.futu.openapi.FTSPI_Conn;
import com.futu.openapi.FTSPI_Trd;
import com.futu.openapi.pb.*;
import org.apache.log4j.Logger;

/**
 *  交易服务
 */

public class SecTrade implements FTSPI_Conn, FTSPI_Trd {
    FTAPI_Conn_Trd trd = new FTAPI_Conn_Trd();
    static Logger log = Logger.getLogger(SecTrade.class.getName());

   public SecTrade() {
        trd.setClientInfo("javaclient", 1);  //设置客户端信息
        trd.setConnSpi(this);  //设置连接相关回调
        trd.setTrdSpi(this);   //设置交易相关回调
    }

    //连接OpenD
    void start() {
        trd.initConnect(BrokerConfig.getOpendIP(), BrokerConfig.getOpendPort(), false);
    }

    //解锁交易
    void unlockTrade() {
        TrdUnlockTrade.C2S c2s = TrdUnlockTrade.C2S.newBuilder()
                .setUnlock(true)
                .setPwdMD5(BrokerConfig.getUnlockTradePwdMd5())
                .build();
        TrdUnlockTrade.Request req = TrdUnlockTrade.Request.newBuilder().setC2S(c2s).build();
        trd.unlockTrade(req);
    }

    //获取交易账号列表
    void getAccList() {
        TrdGetAccList.C2S c2s = TrdGetAccList.C2S.newBuilder().setUserID(BrokerConfig.getUserID()).build();
        TrdGetAccList.Request req = TrdGetAccList.Request.newBuilder().setC2S(c2s).build();
        trd.getAccList(req);
    }

    //下单

    /**
     *
     * @param localOrder
     * @param OrderEnv
     * @return
     */
    int placeOrder(LocalOrder localOrder, int OrderEnv) {
        TrdCommon.TrdHeader header = TrdCommon.TrdHeader.newBuilder()
                .setTrdEnv(OrderEnv)
//                .setTrdEnv(TrdCommon.TrdEnv.TrdEnv_Real_VALUE)
                .setAccID(BrokerConfig.getTrdAcc())
                .setTrdMarket(TrdCommon.TrdMarket.TrdMarket_HK_VALUE)
                .build();
        TrdPlaceOrder.C2S c2s = TrdPlaceOrder.C2S.newBuilder()
                .setPacketID(trd.nextPacketID())
                .setHeader(header)
                .setTrdSide(localOrder.getTrdSide())
                .setOrderType(localOrder.getOrderType())
//                .setOrderType(TrdCommon.OrderType.OrderType_Normal_VALUE)
                .setCode(localOrder.getCode())
                .setQty(localOrder.trdQty)
                .setPrice(localOrder.getPrice())
                .setAdjustPrice(true)
                .setSecMarket(localOrder.getMarket())
                .build();
        TrdPlaceOrder.Request req = TrdPlaceOrder.Request.newBuilder().setC2S(c2s).build();
        log.info("Sending the order request ");
        return trd.placeOrder(req);

    }

    //订阅交易推送，否则不会收到订单相关通知。
    void subAccPush() {
        TrdSubAccPush.C2S c2s = TrdSubAccPush.C2S.newBuilder().addAccIDList(BrokerConfig.getTrdAcc()).build();
        TrdSubAccPush.Request req = TrdSubAccPush.Request.newBuilder().setC2S(c2s).build();
        trd.subAccPush(req);
    }

    //与OpenD连接和初始化完成，可以进行各种业务请求。如果ret为false，表示失败，desc中有错误信息
    public void onInitConnect(FTAPI_Conn client, long errCode, String desc) {
        System.out.printf("Trd onInitConnect: ret=%b desc=%s connID=%d\n", errCode, desc, client.getConnectID());
        if (errCode != 0)
            return;
//        getAccList();
        unlockTrade();
    }

    //连接断开
    public void onDisconnect(FTAPI_Conn client, long errCode) {
        System.out.printf("Trd onDisConnect: %d\n", errCode);
    }

    public void onReply_GetAccList(FTAPI_Conn client, int nSerialNo, TrdGetAccList.Response rsp) {
        System.out.printf("Reply GetAccList: %d %s\n", nSerialNo, rsp.toString());
    }

    public void onReply_UnlockTrade(FTAPI_Conn client, int nSerialNo, TrdUnlockTrade.Response rsp) {
        System.out.printf("Reply UnlockTrade: %d %s\n", nSerialNo, rsp.toString());
        subAccPush();
//        placeOrder();
    }

    public void onReply_SubAccPush(FTAPI_Conn client, int nSerialNo, TrdSubAccPush.Response rsp) {
        System.out.printf("Reply SubAccPush: %d %s\n", nSerialNo, rsp.toString());
    }

    public void onReply_PlaceOrder(FTAPI_Conn client, int nSerialNo, TrdPlaceOrder.Response rsp) {
        long orderID = rsp.getS2C().getOrderID();
        System.out.printf("Reply PlaceOrder: %d %s\n", nSerialNo, rsp.toString());
    }


    public void onPush_UpdateOrder(FTAPI_Conn client, TrdUpdateOrder.Response rsp) {
        TrdCommon.Order order = rsp.getS2C().getOrder();
        OrderOps.updateLocalOrderStatus(order);


        System.out.printf("Push UpdateOrder: %s\n", rsp.toString());
    }

    public void onPush_UpdateOrderFill(FTAPI_Conn client, TrdUpdateOrderFill.Response rsp) {
        System.out.printf("Push UpdateOrderFill: %s\n", rsp.toString());
    }
}